/**
	Copyright (c) 2011 ATTi 
	All rights reserved.
	Author: Michael Shu
	Purpose : Purpose : used for data migration in NADM.
	Project : NADM, AAS, CMR
	Date: 3/15/2011
	Test merge trunk
*/

/****
Step 1. (Pre-deploy)  Use Data loader to update all Account Status to 'Draft'
Step 2. (Post-deploy) Execute all CMR and AAS Data migration scripts step by step.
Step 3. (Post-deploy) Use Data loader to update all Account Status to 'Active'
***/

global class tests implements Database.Batchable<sObject>, Database.Stateful{
	/*
	public Boolean isTest = true;
	public ID TEMP_AAS_AGENCY_ID = null;
	public ID TEMP_AAS_MASTER_CLIENT_ID = null;
	public ID TEMP_NS_MASTER_CLIENT_ID = null;
	
	// Temp Account Name 
	private static String TEMP_AAS_AGENCY_NAME = 'TEMP AAS AGENCY NADM';
	private static String TEMP_AAS_MASTER_CLIENT_NAME = 'TEMP AAS MASTER CLIENT NADM';
	private static String TEMP_NS_MASTER_CLIENT_NAME = 'TEMP NS MASTER CLIENT NADM';
	private static String Silvia_Brogan = 'Silvia Brogan';
	private static String Christopher_Sprauve = 'Christopher Sprauve';
	
	// Account Record Type
	// AAS
	private static String AAS_Agency = 'AAS Agency';
	private static String AAS_Agency_Group = 'AAS Agency Group';
	private static String AAS_Master_Client = 'AAS Master Client';
	private static String AAS_Sales_Account = 'AAS Sales Account';
	private static String Agency_Managed_Customer_Ingenio = 'Agency Managed Customer - Ingenio';
	private static set<String> AAS_RTs = new set<String>{AAS_Agency, AAS_Agency_Group, AAS_Master_Client, AAS_Sales_Account, Agency_Managed_Customer_Ingenio};
	// CMR
	private static String CMR_Agency = 'CMR Agency';
	private static String CMR_Agency_Client = 'CMR Agency Client';
	private static String CMR_Group = 'CMR Group';
	private static String NS_Master_Client = 'NS Master Client';
	private static String National_Managed_Customer_AFrontier = 'National Managed Customer - AFrontier';

	// Opportunity Record Type
	private static String Advanced_Ad_Solutions = 'Advanced Ad Solutions';
	// Others
	private static String Draft = 'Draft';
	private static String AAS_step1_1_Merge_AAS_sales_accounts = 'AAS_step1_1_Merge_AAS_sales_accounts';
	private static String AAS_step2_Create_AAS_sales_accounts = 'AAS_step2_Create_AAS_sales_accounts';
	private static String AAS_step5_AAS_Sales_Account = 'AAS_step5_AAS_Sales_Account';
	private static String AAS_step6_AAS_Opportunities = 'AAS_step6_AAS_Opportunities';
	private static String AAS_step7_Create_AAS_Ingenio_Account = 'AAS_step7_Create_AAS_Ingenio_Account';
	
	private String query;
	private String command;
	
	global tests(){
		list<Account> tempAccts = [select Id, Name from Account where Name =: TEMP_AAS_AGENCY_NAME or Name =: TEMP_AAS_MASTER_CLIENT_NAME or Name =: TEMP_NS_MASTER_CLIENT_NAME];
		list<User> users = [select Id, Name from User where Name =: Silvia_Brogan or Name =: Christopher_Sprauve];
		for(Account a : tempAccts){
			if(a.Name == TEMP_AAS_AGENCY_NAME){
				TEMP_AAS_AGENCY_ID = a.Id;	
			}else if(a.Name == TEMP_AAS_MASTER_CLIENT_NAME){
				TEMP_AAS_MASTER_CLIENT_ID = a.Id;
			}else if(a.Name == TEMP_NS_MASTER_CLIENT_NAME){
				TEMP_NS_MASTER_CLIENT_ID = a.Id;
			}
		}
		ID uId_Silvia_Brogan = UserInfo.getUserId();
		ID uId_Christopher_Sprauve = UserInfo.getUserId();
		for(User u : users){
			if(u.Name == Silvia_Brogan){
				uId_Silvia_Brogan = u.Id;
			}else if(u.Name == Christopher_Sprauve){
				uId_Christopher_Sprauve = u.Id;
			}		
		}
		if(TEMP_AAS_AGENCY_ID == null){
			Account a1 = new Account();
			a1.Name = TEMP_AAS_AGENCY_NAME;
			a1.AAS_Agency_ID__c = '900001';
			a1.Account_Status__c = Draft;
			a1.RecordTypeId = RecordTypeHelper.GetRecordTypeId('Account', AAS_Agency);
			a1.OwnerId = uId_Christopher_Sprauve;
			Database.Saveresult s_rst1 = Database.insert(a1);
			TEMP_AAS_AGENCY_ID = s_rst1.getID();
		}
		if(TEMP_AAS_MASTER_CLIENT_ID == null){
			Account a2 = new Account();
			a2.Name = TEMP_AAS_MASTER_CLIENT_NAME;
			a2.Master_Client_ID__c = '90000001';
			a2.Account_Status__c = Draft;
			a2.RecordTypeId = RecordTypeHelper.GetRecordTypeId('Account', AAS_Master_Client);
			a2.OwnerId = uId_Christopher_Sprauve;
			Database.Saveresult s_rst2 = Database.insert(a2);	
			TEMP_AAS_MASTER_CLIENT_ID = s_rst2.getID();			
		}
		if(TEMP_NS_MASTER_CLIENT_ID == null){
			Account a3 = new Account();
			a3.Name = TEMP_NS_MASTER_CLIENT_NAME;
			a3.Master_Client_ID__c = '90000002';
			a3.Account_Status__c = Draft;
			a3.RecordTypeId = RecordTypeHelper.GetRecordTypeId('Account', NS_Master_Client);
			a3.OwnerId = uId_Silvia_Brogan;
			Database.Saveresult s_rst3 = Database.insert(a3);
			TEMP_NS_MASTER_CLIENT_ID = s_rst3.getID();	
		}
	}	
	
	// CMR methods
	//----------------- Post-Deploy------------------
	public void CMR_step1_CMR_Group(){
		list<Account> acct = [select id, NASA_ID__c, CMR_Group_ID__c from Account where RecordType.Name =: CMR_Group and Account_Status__c =: Draft];
		list<Account> acct_to_update_c1 = new list<Account>();
		for(Account a : acct){
			if(a.NASA_ID__c != a.CMR_Group_ID__c){
				a.NASA_ID__c = a.CMR_Group_ID__c;
				acct_to_update_c1.add(a);
			}
		}
		if(!this.isTest) {update acct_to_update_c1;}
	}
	
	public void CMR_step2_CMR_Agency(){
		list<Account> acct = [select id, Agency_ID__c, NASA_ID__c, CMR_ID__c from Account where RecordType.Name =: CMR_Agency and Account_Status__c =: Draft];
		list<Account> acct_to_update_c2 = new list<Account>();
		for(Account a : acct){
			if(a.Agency_ID__c != a.CMR_ID__c || a.NASA_ID__c != a.CMR_ID__c){
				a.Agency_ID__c = a.CMR_ID__c;
				a.NASA_ID__c = a.CMR_ID__c;
				acct_to_update_c2.add(a);
			}
		}
		if(!this.isTest) {update acct_to_update_c2;}
	}	
	
	public void CMR_step3_CMR_Master_Client(){
		list<Account> acct = [select id, NASA_ID__c, Master_Client_ID__c from Account where RecordType.Name =: NS_Master_Client and Account_Status__c =: Draft];
		list<Account> acct_to_update_c3 = new list<Account>();
		for(Account a : acct){
			if(a.NASA_ID__c != a.Master_Client_ID__c){
				a.NASA_ID__c = a.Master_Client_ID__c;
				acct_to_update_c3.add(a);
			}
		}
		if(!this.isTest) {update acct_to_update_c3;}
	}
	
	public void CMR_step4_CMR_Agency_Client(){
		list<Account> acct = [select id, Master_Client__c, ParentId, Agency__c, CMR_Client_Code_Text__c, NASA_ID__c, Agency__r.Agency_ID__c, Client_Number__c from Account where RecordType.Name =: CMR_Agency_Client and Account_Status__c =: Draft];
		list<Account> acct_to_update_c4 = new list<Account>();
		for(Account a : acct){
			String combined = a.Agency__r.Agency_ID__c + '-' + a.Client_Number__c;
			if(a.Master_Client__c != TEMP_NS_MASTER_CLIENT_ID || a.ParentId != a.Agency__c || a.CMR_Client_Code_Text__c != combined || a.NASA_ID__c != combined){
				a.Master_Client__c = TEMP_NS_MASTER_CLIENT_ID;
				a.ParentId = a.Agency__c;
				a.CMR_Client_Code_Text__c = combined;
				a.NASA_ID__c = combined;
				acct_to_update_c4.add(a);
			}
		}
		if(!this.isTest) {update acct_to_update_c4;}
	}
		
	// AAS methods
	//----------------- Post-Deploy------------------
	public void AAS_step1_Update_Other_Record_Types_To_AAS_Sales_Accounts(){ 
		list<Opportunity> opps = [select id, AccountId, AAS_Agency__c , AAS_Master_Client__c from Opportunity where RecordType.Name =: Advanced_Ad_Solutions and Account.RecordType.Name Not IN: AAS_RTs];
		set<ID> acctIds = new set<ID>();
		for(Opportunity o : opps){
			acctIds.add(o.AccountId);
		}
		list<Account> accts = [select id from Account where Id IN: acctIds];
		ID AAS_Sales_Account_RT_ID = RecordTypeHelper.GetRecordTypeId('Account', AAS_Sales_Account);
		for(Account a : accts){
			a.Account_Status__c = Draft;
		}
		if(!this.isTest) {update accts;}
		for(Account a : accts){
			a.RecordTypeId = AAS_Sales_Account_RT_ID;
		}	
		if(!this.isTest) {update accts;}
		list<Opportunity> opps_to_update = [select id, AAS_Agency__c , AAS_Master_Client__c from Opportunity where RecordType.Name !=: Advanced_Ad_Solutions and Account.RecordType.Name =: AAS_Sales_Account 
		                                                                     and AAS_Agency__c != null and AAS_Master_Client__c != null];
		ID Advanced_Ad_Solutions_Opp_RT_ID = RecordTypeHelper.GetRecordTypeId('Opportunity', Advanced_Ad_Solutions);
		for(Opportunity o : opps_to_update){
			if(o.AAS_Agency__c != null || o.AAS_Master_Client__c != null){
				o.RecordTypeId = Advanced_Ad_Solutions_Opp_RT_ID;
			}
		}
		if(!this.isTest) {update opps_to_update;}
	}
	
	public void AAS_step1_1_Merge_AAS_sales_accounts(){
		list<Opportunity> opps;
		
		if(!this.isTest){ 
			opps = [Select ID, Name, AccountId, Account.Name, AAS_Agency__c, AAS_Master_Client__c, LastModifiedDate 
		            from Opportunity 
		            where RecordType.Name =: Advanced_Ad_Solutions and AAS_Agency__c != null and AAS_Master_Client__c != null
		            order by AAS_Agency__c, AAS_Master_Client__c, AccountId, LastModifiedDate asc];
		}else{
			opps = [Select ID, Name, AccountId, Account.Name, AAS_Agency__c, AAS_Master_Client__c, LastModifiedDate 
		            from Opportunity 
		            where RecordType.Name =: Advanced_Ad_Solutions and AAS_Agency__c != null and AAS_Master_Client__c != null
		            order by AAS_Agency__c, AAS_Master_Client__c, AccountId, LastModifiedDate asc limit 100];
		}
		set<ID> acctIds = new set<ID>();
		for(Opportunity o : opps){
			acctIds.add(o.AccountId);
		}
		map<ID, Account> accts = new map<ID, Account>([select id from Account where id IN: acctIds]);
		Integer max = opps.size();
		for(Integer i = 0; i < max - 1 ; i ++ ){
			Integer j = i + 1;
			Boolean isDifferent = opps[i].AAS_Agency__c == opps[j].AAS_Agency__c 
			                   && opps[i].AAS_Master_Client__c == opps[j].AAS_Master_Client__c 
			                   && opps[i].AccountId != opps[j].AccountId;
			if(isDifferent){
				Account master = accts.get(opps[j].AccountId); // keep as the master acount
				System.debug('Merge report : Account Id : ' + opps[i].AccountId + ' Name = ' + opps[i].Account.Name 
			   	        + ' has been merged to Account Id ' + opps[j].AccountId + ' Name = ' + opps[j].Account.Name);
			   	if(!this.isTest) {
			   		merge master opps[i].AccountId; // merge opps[i].AccountId into opps[j].AccountId
			   	}
			}
		}
	}
	
	public void AAS_step2_Create_AAS_sales_accounts(){ 
		this.command = AAS_step2_Create_AAS_sales_accounts;
		database.executebatch(this);
	}
	
	public void AAS_step3_AAS_Agency(){
		list<Account> acct = [select id, Agency_ID__c, NASA_ID__c, AAS_Agency_ID__c from Account where RecordType.Name =: AAS_Agency and Account_Status__c =: Draft];
		list<Account> acct_to_update_a3 = new list<Account>();
		for(Account a : acct){
			if(a.Agency_ID__c != a.AAS_Agency_ID__c || a.NASA_ID__c != a.AAS_Agency_ID__c){
				a.Agency_ID__c = a.AAS_Agency_ID__c;
				a.NASA_ID__c = a.AAS_Agency_ID__c;
				acct_to_update_a3.add(a);
			}
		}
		if(!this.isTest) {update acct_to_update_a3;}
	}
	
	public void AAS_step4_AAS_Master_Client(){
		list<Account> acct = [select id, NASA_ID__c, Master_Client_ID__c from Account where RecordType.Name =: AAS_Master_Client and Account_Status__c =: Draft];
		list<Account> acct_to_update_a4 = new list<Account>();
		for(Account a : acct){
			if(a.NASA_ID__c != a.Master_Client_ID__c){
				a.NASA_ID__c = a.Master_Client_ID__c;
				acct_to_update_a4.add(a);
			}
		}
		if(!this.isTest) {update acct_to_update_a4;}
	}

	public void AAS_step5_AAS_Sales_Account(){
		this.command = AAS_step5_AAS_Sales_Account;
		database.executebatch(this);
	}
	
	public void AAS_step6_AAS_Opportunities(){
		this.command = AAS_step6_AAS_Opportunities;
		database.executebatch(this);
	}

	public void AAS_step7_Create_AAS_Ingenio_Account(){
		this.command = AAS_step7_Create_AAS_Ingenio_Account;
		database.executebatch(this);
	}
	
	global Database.Querylocator start(Database.BatchableContext bc){ 
		if(this.command == AAS_step2_Create_AAS_sales_accounts){
			this.query = ' select id, ParentId, AAS_Agency_Name__c, Master_Client__c, OwnerId, Name, RecordTypeId, CORPORATE_COUNTRY__C, PHONE, BILLING_CONTACT__C '
			          +  ' , BILLINGSTREET, BILLINGCITY, BILLINGSTATE, BILLINGPOSTALCODE, BILLINGCOUNTRY, CONTACT_PHONE__C '
			          +  ' , CONTACT_FAX__C, CONTACT_EMAIL__C, PAYMENT_SCHEDULE__C, PAYMENT_METHOD__C '
			          +  ' , (select id, AAS_Agency__c, AAS_Master_Client__c from Opportunities) '
			          +  ' from Account where RecordType.Name =: AAS_Sales_Account and Account_Status__c =: Draft ';
		}else if(this.command == AAS_step5_AAS_Sales_Account){
			this.query = ' select id, ParentId, Client_Number__c, NASA_ID__c, AAS_Agency_Name__c, AAS_Agency_Name__r.Agency_ID__c, Master_Client__r.Master_Client_ID__c from Account where RecordType.Name =: AAS_Sales_Account and Account_Status__c =: Draft ';
		}else if(this.command == AAS_step6_AAS_Opportunities){
			this.query = ' select id, (select id from Opportunities) from Account where RecordType.Name =: AAS_Sales_Account and Account_Status__c =: Draft ';
		}else if(this.command == AAS_step7_Create_AAS_Ingenio_Account){
			this.query = ' select id, OwnerId, Name, Ingenio_UserID__c, Ingenio_UserName__c, Ingenio_Member_Status__c from Account where RecordType.Name =: AAS_Sales_Account and INGENIO_USERID__C != null ';
		}
		if(this.isTest){
			this.query += ' limit 100 ';
		}
        return Database.getQueryLocator(this.query);		
	}
	
	global void execute(Database.BatchableContext bc, List<sObject> scope){
		if(this.command == AAS_step2_Create_AAS_sales_accounts){
			list<Account> acct_to_insert = new list<Account>();
			list<Account> acct_to_update = new list<Account>();
			map<ID, Opportunity> all_opps = new map<ID, Opportunity>();
			set<ID> masterIds = new set<ID>();
			masterIds.add(TEMP_AAS_MASTER_CLIENT_ID);
			for(sObject obj : scope){
				Account a = (Account) obj;
				for(Opportunity o : a.Opportunities){
					masterIds.add(o.AAS_Master_Client__c);
				}
			}
			map<ID, Account> master_accts = new map<ID, Account>([select id, Master_Client_ID__c from Account where id IN: masterIds]);
			
			for(sObject obj : scope){
				Account a = (Account) obj;
				map<String, set<String>> a_and_m_ids = new map<String, set<String>>();
				for(Opportunity o : a.Opportunities){
					if(o.AAS_Agency__c != null || o.AAS_Master_Client__c != null){
						System.debug(' AccountId = ' + a.Id + ' OppId = ' + o.Id);
						String agencyId = (o.AAS_Agency__c != null)? o.AAS_Agency__c : TEMP_AAS_AGENCY_ID;
						String master_clientId = (o.AAS_Master_Client__c != null)? o.AAS_Master_Client__c : TEMP_AAS_MASTER_CLIENT_ID;
						String combined = agencyId + ';' + master_clientId;
						if(a_and_m_ids.containsKey(combined)){
							set<String> strs = a_and_m_ids.get(combined);
							strs.add(o.Id);
							a_and_m_ids.put(combined, strs);
						}else{
							a_and_m_ids.put(combined, new set<String>{o.Id});
						}
						all_opps.put(o.Id, o);
					}
				}
				Integer i = 0;
				for(String s : a_and_m_ids.keySet()){
					System.debug(' In the loop AccountId = ' + a.Id + ' OppId = ' + s);
					String[] ss = s.split(';');
					if(i == 0){
						if(a.AAS_Agency_Name__c != ss[0] || a.ParentId != ss[0] || a.Master_Client__c != ss[1]){
							a.AAS_Agency_Name__c = ss[0];
							a.ParentId = ss[0];
							a.Master_Client__c = ss[1];
							a.Client_Number__c = (master_accts.get(ss[1]) == null)? '' : master_accts.get(ss[1]).Master_Client_ID__c;
							System.debug(' In the loop To update AccountId = ' + a.Id + ' a.AAS_Agency_Name__c = ' + a.AAS_Agency_Name__c + ' a.Master_Client__c = ' + a.Master_Client__c);
							acct_to_update.add(a);
						}
					}else if(i > 0){
						Account new_account = new Account();
						new_account.AAS_Agency_Name__c = ss[0];
						new_account.ParentId = ss[0];
						new_account.Master_Client__c = ss[1];
						for(String oId : a_and_m_ids.get(s)){
							new_account.Line_Of_Business__c = oId + ';'; // used to store Opportunity Id
							System.debug(' In the loop new_account.Line_Of_Business__c = ' + new_account.Line_Of_Business__c);
						}
						new_account.Line_Of_Business__c.substring(0, new_account.Line_Of_Business__c.lastIndexOf(';'));
						new_account.Account_Status__c = Draft;
						new_account.OwnerId = a.OwnerId;
						new_account.RecordTypeId = a.RecordTypeId;
						new_account.Name = a.Name + '-' + i;
						new_account.CORPORATE_COUNTRY__C = a.CORPORATE_COUNTRY__C;
						new_account.PHONE = a.PHONE;
						new_account.BILLING_CONTACT__C = a.BILLING_CONTACT__C;
						new_account.BILLINGSTREET = a.BILLINGSTREET;
						new_account.BILLINGCITY = a.BILLINGCITY;
						new_account.BILLINGSTATE = a.BILLINGSTATE;
						new_account.BILLINGPOSTALCODE = a.BILLINGPOSTALCODE;
						new_account.BILLINGCOUNTRY = a.BILLINGCOUNTRY;
						new_account.CONTACT_PHONE__C = a.CONTACT_PHONE__C;
						new_account.CONTACT_FAX__C = a.CONTACT_FAX__C;
						new_account.CONTACT_EMAIL__C = a.CONTACT_EMAIL__C;
						new_account.PAYMENT_SCHEDULE__C = a.PAYMENT_SCHEDULE__C;
						new_account.PAYMENT_METHOD__C = a.PAYMENT_METHOD__C;
						acct_to_insert.add(new_account);
					}
					i++;
				}
			}
			if(!this.isTest) {update acct_to_update;}
			DataBase.Saveresult[] a_rsts;
			if(!this.isTest) {a_rsts = DataBase.insert(acct_to_insert);}
			if(a_rsts != null){
				set<ID> newIds = new set<ID>();
				list<Opportunity> opp_to_update = new list<Opportunity>();
				for(DataBase.Saveresult rst : a_rsts){
					newIds.add(rst.getID());
				}
				list<Account> new_accts = [select Id, Line_Of_Business__c from Account where Id IN: newIds];
				for(Account a : new_accts){
					if(a.Line_Of_Business__c != null){
						String[] oIds_split =  a.Line_Of_Business__c.split(';');
						for(String s : oIds_split){
							Opportunity o = all_opps.get(s);
							o.AccountId = a.Id;
							opp_to_update.add(o);
						}
					}
				}
				if(!this.isTest) {update opp_to_update;}
			}
		}else if(this.command == AAS_step5_AAS_Sales_Account){
			list<Account> accts = new list<Account>();
			for(sObject obj : scope){
				Account a = (Account) obj;
				String combined = a.AAS_Agency_Name__r.Agency_ID__c + '-' + a.Master_Client__r.Master_Client_ID__c;
				if(a.ParentId != a.AAS_Agency_Name__c || a.Client_Number__c != a.Master_Client__r.Master_Client_ID__c || a.NASA_ID__c != combined){
					a.ParentId = a.AAS_Agency_Name__c;
					a.Client_Number__c = a.Master_Client__r.Master_Client_ID__c;
					a.NASA_ID__c = combined;
					accts.add(a);
				}
			}
			if(!this.isTest) {update accts;}
		}else if(this.command == AAS_step6_AAS_Opportunities){
			list<Opportunity> opps = new list<Opportunity>();
			for(sObject obj : scope){
				Account a = (Account) obj;
				Integer i = 1;
				for(Opportunity o : a.Opportunities){
					o.PO_Index__c = i;
					i++;
					opps.add(o);
				}
			}
			if(!this.isTest) {update opps; }
		}else if(this.command == AAS_step7_Create_AAS_Ingenio_Account){
			list<Account> ingenio_accts = new list<Account>();
			list<Account> sales_accts = new list<Account>();
			ID AAS_Ingenio_Account_RT_ID = RecordTypeHelper.GetRecordTypeId('Account', Agency_Managed_Customer_Ingenio);
			for(sObject obj : scope){
				Account a = (Account) obj;
				Account newItem = new Account();
				newItem.Account_Status__c = Draft;
				newItem.RecordTypeId = AAS_Ingenio_Account_RT_ID;
				newItem.ParentId = a.Id;
				newItem.Name = a.Name + ' - Ingenio';
				newItem.OwnerId = a.OwnerId;
				newItem.Ingenio_UserID__c = a.Ingenio_UserID__c;
				newItem.Ingenio_UserName__c = a.Ingenio_UserName__c;
				newItem.Ingenio_Member_Status__c = a.Ingenio_Member_Status__c;
				ingenio_accts.add(newItem);
				a.Ingenio_UserID__c = '';
				a.Ingenio_UserName__c = '';
				a.Ingenio_Member_Status__c = '';
				sales_accts.add(a);
			}
			if(!this.isTest) {
				Savepoint sp = Database.setSavepoint();
				try{ 
					update sales_accts;
					insert ingenio_accts;
				}catch(Exception ex){
					Database.rollback(sp);
					mailAnyExceptionToMe('update sales_accts or insert ingenio_accts fail', ex);
				}	
			}
		}
	}
	
	global void finish(Database.BatchableContext bc){
	}
	
	public static testMethod void testrun() {
		init();
		Test.startTest();
		
		tests t1 = new tests();
		// Post-deploy
		t1.CMR_step1_CMR_Group();
		t1.CMR_step2_CMR_Agency();
		t1.CMR_step3_CMR_Master_Client();
		t1.CMR_step4_CMR_Agency_Client();
		
		tests t2 = new tests();
		// Post-deploy
		t2.AAS_step1_Update_Other_Record_Types_To_AAS_Sales_Accounts(); // Need attention!!!!!!!!!, Done
		t2.AAS_step2_Create_AAS_sales_accounts(); // Need attention!!!!!!!!!
		t2.AAS_step3_AAS_Agency();
		t2.AAS_step4_AAS_Master_Client();
		t2.AAS_step5_AAS_Sales_Account();
		t2.AAS_step6_AAS_Opportunities();
		t2.AAS_step7_Create_AAS_Ingenio_Account();
		
		Test.stopTest();
	}

    public static testMethod void runMergeTest() {
		init();
		tests t3 = new tests();
		t3.AAS_step1_1_Merge_AAS_sales_accounts();
		try{
			throw new ExtendException('Test email');
		}catch(Exception e){
			mailAnyExceptionToMe('Test email', e);
		}
	}
	
	public class ExtendException extends Exception {}
	
	private static void init(){
		list<Account> accts_to_delete = [select id from Account where Name =: TEMP_AAS_AGENCY_NAME or Name =: TEMP_AAS_MASTER_CLIENT_NAME or Name =: TEMP_NS_MASTER_CLIENT_NAME];
		delete accts_to_delete;
	}
	
	private void test1(){
Holiday h = new Holiday();
h.IsAllDay = true;
h.ActivityDate = date.newInstance(2011, 1, 1);
h.RecurrenceStartDate = date.newInstance(2011, 1, 1);
h.RecurrenceDayOfMonth = 4;
h.RecurrenceDayOfWeekMask = null;
h.IsRecurrence  = true;
h.Name = 'Independence Day';
h.RecurrenceInstance = null;
h.Description = '7/4';
h.RecurrenceMonthOfYear = 'July';
h.RecurrenceType = 'RecursYearly';
insert h;


h = new Holiday();
h.IsAllDay = true;
h.ActivityDate = date.newInstance(2011, 1, 1);
h.RecurrenceStartDate = date.newInstance(2011, 1, 1);
h.RecurrenceDayOfMonth = 1;
h.RecurrenceDayOfWeekMask = null;
h.IsRecurrence  = true;
h.Name = 'New Year\'s Day';
h.RecurrenceInstance = null;
h.Description = '1/1';
h.RecurrenceMonthOfYear = 'January';
h.RecurrenceType = 'RecursYearly';
insert h;

h = new Holiday();
h.IsAllDay = true;
h.ActivityDate = date.newInstance(2011, 1, 1);
h.RecurrenceStartDate = date.newInstance(2011, 1, 1);
h.RecurrenceDayOfMonth = 25;
h.RecurrenceDayOfWeekMask = null;
h.IsRecurrence  = true;
h.Name = 'Christmas Day';
h.RecurrenceInstance = null;
h.Description = '12/25';
h.RecurrenceMonthOfYear = 'December';
h.RecurrenceType = 'RecursYearly';
insert h;

h = new Holiday();
h.IsAllDay = true;
h.ActivityDate = date.newInstance(2011, 1, 1);
h.RecurrenceStartDate = date.newInstance(2011, 1, 1);
h.RecurrenceDayOfMonth = null;
h.RecurrenceDayOfWeekMask = 2;
h.IsRecurrence  = true;
h.Name = 'Memorial Day';
h.RecurrenceInstance = 'Last';
h.Description = 'Last Monday in May.';
h.RecurrenceMonthOfYear = 'May';
h.RecurrenceType = 'RecursYearlyNth';
insert h;

h = new Holiday();
h.IsAllDay = true;
h.ActivityDate = date.newInstance(2011, 1, 1);
h.RecurrenceStartDate = date.newInstance(2011, 1, 1);
h.RecurrenceDayOfMonth = null;
h.RecurrenceDayOfWeekMask = 2;
h.IsRecurrence  = true;
h.Name = 'Labor Day';
h.RecurrenceInstance = 'First';
h.Description = '1st Monday in September.';
h.RecurrenceMonthOfYear = 'September';
h.RecurrenceType = 'RecursYearlyNth';
insert h;

h = new Holiday();
h.IsAllDay = true;
h.ActivityDate = date.newInstance(2011, 1, 1);
h.RecurrenceStartDate = date.newInstance(2011, 1, 1);
h.RecurrenceDayOfMonth = null;
h.RecurrenceDayOfWeekMask = 32;
h.IsRecurrence  = true;
h.Name = 'Day after Thanksgiving';
h.RecurrenceInstance = 'Fourth';
h.Description = '4th Friday in November.';
h.RecurrenceMonthOfYear = 'November';
h.RecurrenceType = 'RecursYearlyNth';
insert h;

h = new Holiday();
h.IsAllDay = true;
h.ActivityDate = date.newInstance(2011, 1, 1);
h.RecurrenceStartDate = date.newInstance(2011, 1, 1);
h.RecurrenceDayOfMonth = null;
h.RecurrenceDayOfWeekMask = 16;
h.IsRecurrence  = true;
h.Name = 'Thanksgiving';
h.RecurrenceInstance = 'Fourth';
h.Description = '4th Thursday in November.';
h.RecurrenceMonthOfYear = 'November';
h.RecurrenceType = 'RecursYearlyNth';
insert h;

h = new Holiday();
h.IsAllDay = true;
h.ActivityDate = date.newInstance(2011, 12, 26);
h.RecurrenceStartDate = null;
h.RecurrenceDayOfMonth = null;
h.RecurrenceDayOfWeekMask = null;
h.IsRecurrence  = false;
h.Name = 'Christmas Day 2011';
h.RecurrenceInstance = null;
h.Description = '12/26/2011';
h.RecurrenceMonthOfYear = null;
h.RecurrenceType = null;
insert h;

h = new Holiday();
h.IsAllDay = true;
h.ActivityDate = date.newInstance(2012, 1, 2);
h.RecurrenceStartDate = null;
h.RecurrenceDayOfMonth = null;
h.RecurrenceDayOfWeekMask = null;
h.IsRecurrence  = false;
h.Name = 'New Year\'s Day 2012';
h.RecurrenceInstance = null;
h.Description = '1/2/2012';
h.RecurrenceMonthOfYear = null;
h.RecurrenceType = null;
insert h;
	}

    public class BusinessHoursCalcException extends Exception {}
	
	public static void uploadusers(){
		String env = '.stageminor';
		String password = '123123a';
		list<String> userlist = new list<String>{
'th0532@noreply.att.com;rc5257;National Marketing Manager;National Sales',
'sm7982@att.com;sm7982;National Sales Operations Director;National Sales Management',
'sb1946@att.com;rm0020;SVP of National Sales;National Sales Assignment Manager',
'ss2814@att.com;jp680g;National Sales Manager;National Sales New Account Manager', 
'rc5257@att.com;jp6949;National Marketing Manager;National Sales Read Only', 

'chucklee@yellowpages.com;jp6825;SVP of National Sales;National Operations', 
'childreth@attinteractive.com;nk6074;Billing;National Ops - Billing',
'dolivares@attinteractive.com;jp6940;Manager, Order Entry;National Ops - Edit Rights', 
'sfdcqeNato@attinteractive.com;sh1234;Sales/Customer Support;National Ops - NO SSO',
'mgoldstein@attinteractive.com;jp6812;Sales/Customer Support;National Ops - Read Only', 
'amcgruder@attinteractive.com;jp708u;Sales/Customer Support;National Ops - Sales Support', 
'cbakofsky@attinteractive.com;jp7097;Manager, Ad Production;Manager, QC' 
		};		
        
        set<String> rolelist = new set<String>();
        set<String> profilelist = new set<String>();
        for(String s : userlist){
        	String [] ss = s.split(';');
        	rolelist.add(ss[2]);
        	profilelist.add(ss[3]);
        }
        list<Profile> profiles = [select Id, Name, IsSsoEnabled from Profile where Name IN: profilelist ]; 
        list<UserRole> roles = [select Id, Name from UserRole where Name IN: rolelist ];
        
        map<String, ID> rolemap = new map<String, ID>();
        map<String, ID> profilemap = new map<String, ID>();
        for(UserRole ur : roles){
        	rolemap.put(ur.Name, ur.Id);
        }
        for(Profile p : profiles){
        	profilemap.put(p.Name, p.Id);
        }
        Boolean isMissing = true;
        for(String s : userlist){
        	String [] ss = s.split(';');
        	if(!rolemap.containsKey(ss[2])){
        		System.debug('User Role <' + ss[2] + '> is missing');
        		isMissing = false;
        	}
        	if(!profilemap.containsKey(ss[3])){
        		System.debug('Profile <' + ss[3] + '> is missing');
        		isMissing = false;
        	}
        }
        System.assert(isMissing, 'missing error');
        
        Integer i = 0;  
        list<User> users = new list<User>();      
        for(String s : userlist){
        	String [] ss = s.split(';');
        	String username = ss[0] + env; 
        	String[] eStr = ss[0].split('@');
        	String email = eStr[0] + env + '@' + eStr[1];
        	String attUid = ss[1];
        	String roleId = rolemap.get(ss[2]);
        	String pId = profilemap.get(ss[3]); 
        	String lastName = 'SFDC QE -- ' + ss[3];
		    User u_new = new User();
			u_new.UserName = username;
			u_new.LastName = lastName;
			u_new.FirstName = '';
			u_new.Email = email;
			u_new.ProfileId = pId;
			u_new.UserRoleId = roleId;
			u_new.Alias = 'qe523' + i;
			u_new.CommunityNickname = 'nick523' + i;
			u_new.TimeZoneSidKey = 'America/Los_Angeles';
			u_new.LocaleSidKey = 'en_US';
			u_new.EmailEncodingKey = 'UTF-8';
			u_new.IsActive = true;
			u_new.LanguageLocaleKey = 'en_US';
			users.add(u_new);
			i++;
        }
        Database.UpsertResult[] sr = Database.upsert(users, User.Fields.Username);
        set<ID> uIds = new set<ID>();
        for(Database.UpsertResult r : sr){
        	uIds.add(r.getId());
        }
        list<User> rst_users = [select Id, UserName, profile.IsSsoEnabled from User where Id IN: uIds];
        for(User u : rst_users){
        	if(u.Profile.IsSsoEnabled){
        		System.debug(u.UserName + ' is sso user : ' + u.Id);
        	}else{
        		System.setPassword(u.Id, password);
        	}
        }
	}
	
	public static void fixPOIndexforAASOpportunity(){
		list<Account> accounts = [select id, (select PO_Index__c from Opportunities order by PO_Index__c asc) from Account where RecordType.Name =: 'AAS Sales Account'];
		list<Opportunity> opps = new list<Opportunity>();
		for(Account a : accounts){
			list<Opportunity> acct_opps = a.Opportunities;
			Boolean isMess = false;
			for(Integer i = 0 ; i < acct_opps.size()-1 ; i++){
				if(acct_opps[i].PO_Index__c == acct_opps[i+1].PO_Index__c){
					isMess = true;
					break;
				}
			}
			if(isMess){
				Integer i = 1;
				for(Opportunity o : acct_opps){
					if(o.PO_Index__c != i ){
						o.PO_Index__c = i;
						opps.add(o);
					}
					i++;
				}
			}
		}
		update opps; 
		set<ID> oppsIds = new set<ID>();
		for(Opportunity o : opps){
			oppsIds.add(o.Id);
		}
		list<Order__c> orders = [select id from Order__c where Opportunity__c IN: oppsIds ];
		update orders;
	}		
	
	
	private static void mailAnyExceptionToMe(String subject, Exception e){
		Messaging.SingleEmailMessage mail =new Messaging.SingleEmailMessage();
	    String[] toAddresses = new String[] {'sshu@attinteractive.com'};
	    mail.setToAddresses(toAddresses);
	    mail.setReplyTo('sshu@attinteractive.com');
	    mail.setSenderDisplayName('Apex error message');
	    mail.setSubject('Data migration :' + subject + ' User Name : ' + UserInfo.getUserName());
	    mail.setPlainTextBody(e.getMessage());
	    Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });		
	}	

	private static void cleanup(){
		List<UserRole> roles = [select id, name, RollupDescription  from UserRole where name like '%–%'or RollupDescription like '%–%'];
		String fromRegExp = '(.*)(\\s*–\\s*)(.*)';
	    String toRegExp   = '$1 - $3';
		for(UserRole r : roles){
			//r.Name = r.Name.replaceAll(fromRegExp, toRegExp);
			//r.RollupDescription = r.Name;
			r.RollupDescription = r.RollupDescription.replaceAll(fromRegExp, toRegExp);
			r.Name = r.RollupDescription;			
		}
		update roles;

		for(UserRole r : roles){
			r.Name = r.Name.replaceAll(fromRegExp, toRegExp);
			r.RollupDescription = r.Name;
		}
		update roles;

        roles = [select id, name, RollupDescription from UserRole where  RollupDescription  != null and RollupDescription  != ''];
		for(UserRole r : roles){
			if(r.Name != r.RollupDescription){
               r.Name = r.RollupDescription;
            }
		}
		update roles;
	}
	*/
/* Naidu Changes	 */

/*
	public static Map<String, String> rolesReLabel = new Map<String, String>{
'Customer Care Director - IR' => 'IOG EAST - Department Director',
'Tier 1 Manager - IR' => 'IOG EAST - Support L1 - Manager',
'Tier 1 Supervisor - IR' => 'IOG EAST - Support L1 - Supervisor',
'Tier 1 CSR - IR' => 'IOG EAST - Support L1 - Rep',
'Tier 2 Manager - IR' => 'IOG EAST - Support L2 - Manager',
'Tier 2 Supervisor - IR' => 'IOG EAST - Support L2 - Supervisor',
'Tier 2 CSR - IR' => 'IOG EAST - Support L2 - Rep',
'Product SME - IR' => 'IOG EAST - Product SME - Rep',
'Product SME - Manager - IR' => 'IOG EAST - Product SME - Manager',
'IOG Fulfillment - Manager - IR' => 'IOG EAST - Receiving - Manager',
'IOG Fulfillment - Rep - IR' => 'IOG EAST - Receiving - Rep',
'Customer Care Director' => 'IOG OOR - Department Director',
'Tier1 Support Rep' => 'CS - Site Customer Support L1 - Rep',
'Tier1 Support Manager' => 'CS - Site Customer Support - Manager',
'Tier2 Support Rep' => 'IOG OOR - Support L1 - Rep',
'Tier2 Support Manager' => 'IOG OOR - Support L1 - Manager',
'Fulfillment Support Rep' => 'IOG OOR - Product SME - Rep',
'Fulfillment Support Manager' => 'IOG OOR - Product SME - Manager',
'Customer Care Executive' => 'IOGCS Executive',
'Account Manager - IR' => 'IOG EAST - Account Manager',
'Operational Analyst - IR' => 'IOG EAST - Analyst'											
};

*/
    public static Map<String, String> rolesNew = new Map<String, String>{
'OOR East and Northwest RVP'=>	'Information Systems',
'OOR East Region Director'=>	'Information Systems',
'OOR Allentown Office' => 'Information Systems',
'OOR Allentown GSM'=>	'Information Systems',
'OOR Allentown DSM1'=>	'Information Systems',
'OOR Allentown MC1'=>	'Information Systems',
'OOR Allentown DSM2'=>	'Information Systems',
'OOR Allentown MC2'=>	'Information Systems',
'OOR Allentown SMC1'=>	'Information Systems',
'OOR Allentown Sales Admin'=>	'Information Systems',
'OOR Boston Office'=>	'Information Systems',
'OOR Boston GSM'=>	'Information Systems',
'OOR Boston DSM1'=>	'Information Systems',
'OOR Boston MC1'=>	'Information Systems',
'OOR Boston DSM2'=>	'Information Systems',
'OOR Boston MC2'=>	'Information Systems',
'OOR Boston DSM3'=>	'Information Systems',
'OOR Boston MC3'=>	'Information Systems',
'OOR Boston SMC1'=>	'Information Systems',
'OOR Boston SMC2'=>	'Information Systems',
'OOR Boston Sales Admin'=>	'Information Systems',
'OOR Long Island Office'=>	'Information Systems',
'OOR Long Island GSM'=>	'Information Systems',
'OOR Long Island DSM1'=>	'Information Systems',
'OOR Long Island MC1'=>	'Information Systems',
'OOR Long Island DSM2'=>	'Information Systems',
'OOR Long Island MC2'=>	'Information Systems',
'OOR Long Island Sales Admin' => 'Information Systems',
'OOR New York Office'=>	'Information Systems',
'OOR New York GSM1'=>	'Information Systems',
'OOR New York GSM2' => 'Information Systems',
'OOR New York DSM1'=>	'Information Systems',
'OOR New York MC1'=>	'Information Systems',
'OOR New York DSM2'=>	'Information Systems',
'OOR New York MC2'=>	'Information Systems',
'OOR New York SMC1'=>	'Information Systems',
'OOR New York SMC2'=>	'Information Systems',
'OOR New York SMC3'=>	'Information Systems',
'OOR New York Sales Admin'=>	'Information Systems',
'OOR Philadelphia Office'=>	'Information Systems',
'OOR Philadelphia GSM'=>	'Information Systems',
'OOR Philadelphia DSM1'=>	'Information Systems',
'OOR Philadelphia MC1'=>	'Information Systems',
'OOR Philadelphia DSM2'=>	'Information Systems',
'OOR Philadelphia MC2'=>	'Information Systems',
'OOR Philadelphia DSM3'=>	'Information Systems',
'OOR Philadelphia MC3'=>	'Information Systems',
'OOR Philadelphia DSM4'=>	'Information Systems',
'OOR Philadelphia MC4'=>	'Information Systems',
'OOR Philadelphia SMC1'=>	'Information Systems',
'OOR Philadelphia Sales Admin'=>	'Information Systems',
'OOR Providence Office'=>	'Information Systems',
'OOR Providence GSM'=>	'Information Systems',
'OOR Providence DSM1'=>	'Information Systems',
'OOR Providence MC1'=>	'Information Systems',
'OOR Providence DSM2'=>	'Information Systems',
'OOR Providence MC2'=>	'Information Systems',
'OOR White Plains Office'=>	'Information Systems',
'OOR White Plains MC1'=>	'Information Systems',
'OOR Northwest Region Director'=>	'Information Systems',
'OOR Denver Office'=>	'Information Systems',
'OOR Denver GSM'=>	'Information Systems',
'OOR Denver DSM1'=>	'Information Systems',
'OOR Denver MC1'=>	'Information Systems',
'OOR Denver DSM2' =>	'Information Systems',
'OOR Denver MC2'=>	'Information Systems',
'OOR Denver DSM3'=>	'Information Systems',
'OOR Denver MC3'=>	'Information Systems',
'OOR Denver SMC1'=>	'Information Systems',
'OOR Denver SMC2'=>	'Information Systems',
'OOR Denver Sales Admin'=>	'Information Systems',
'OOR Portland Office'=>	'Information Systems',
'OOR Portland GSM'=>	'Information Systems',
'OOR Portland DSM1'=>	'Information Systems',
'OOR Portland MC1'=>	'Information Systems',
'OOR Portland DSM2'=>	'Information Systems',
'OOR Portland MC2'=>	'Information Systems',
'OOR Portland DSM3'=>	'Information Systems',
'OOR Portland MC3'=>	'Information Systems',
'OOR Portland Sales Admin'=>	'Information Systems',
'OOR Seattle Office'=>	'Information Systems',
'OOR Seattle GSM'=>	'Information Systems',
'OOR Seattle DSM1'=>	'Information Systems',
'OOR Seattle MC1'=>	'Information Systems',
'OOR Seattle DSM2'=>	'Information Systems',
'OOR Seattle MC2'=>	'Information Systems',
'OOR Seattle DSM3'=>	'Information Systems',
'OOR Seattle MC3'=>	'Information Systems',
'OOR Seattle SMC1'=>	'Information Systems',
'OOR Seattle SMC2'=>	'Information Systems',
'OOR Seattle Sales Admin'=>	'Information Systems',
//'OOR SLC Office'=>	'Information Systems',
'OOR Minneapolis Office'=>	'Information Systems',
'OOR Minneapolis GSM'=>	'Information Systems',
'OOR Minneapolis DSM1'=>	'Information Systems',
'OOR Minneapolis MC1'=>	'Information Systems',
'OOR Minneapolis DSM2'=>	'Information Systems',
'OOR Minneapolis MC2'=>	'Information Systems',
'OOR Minneapolis DSM3'=>	'Information Systems',
'OOR Minneapolis MC3'=>	'Information Systems',
'OOR Minneapolis SMC1'=>	'Information Systems',
'OOR Minneapolis SMC2'=>	'Information Systems',
'OOR Minneapolis Sales Admin'=>	'Information Systems',
'OOR Pittsburgh Office'=>	'Information Systems',
'OOR Pittsburgh GSM'=>	'Information Systems',
'OOR Pittsburgh DSM1'=>	'Information Systems',
'OOR Pittsburgh MC1'=>	'Information Systems',
'OOR Pittsburgh DSM2'=>	'Information Systems',
'OOR Pittsburgh MC2'=>	'Information Systems',
'OOR Pittsburgh DSM3'=>	'Information Systems',
'OOR Pittsburgh MC3'=>	'Information Systems',
'OOR Pittsburgh SMC1'=>	'Information Systems',
'OOR Pittsburgh Sales Admin'=>	'Information Systems',
'OOR Mid Atlantic and Mountain West RVP'=>	'Information Systems',
'OOR Baltimore Office'=>	'Information Systems',
'OOR Baltimore GSM'=>	'Information Systems',
'OOR Baltimore DSM1'=>	'Information Systems',
'OOR Baltimore MC1'=>	'Information Systems',
'OOR Baltimore DSM2'=>	'Information Systems',
'OOR Baltimore MC2'=>	'Information Systems',
'OOR Baltimore DSM3'=>	'Information Systems',
'OOR Baltimore MC3'=>	'Information Systems',
'OOR Baltimore SMC1'=>	'Information Systems',
'OOR Baltimore Sales Admin'=>	'Information Systems',
'OOR Richmond Office'=>	'Information Systems',
'OOR Richmond GSM'=>	'Information Systems',
'OOR Richmond DSM1'=>	'Information Systems',
'OOR Richmond MC1'=>	'Information Systems',
'OOR Richmond DSM2'=>	'Information Systems',
'OOR Richmond MC2'=>	'Information Systems',
'OOR Richmond SMC1'=>	'Information Systems',
'OOR Richmond Sales Admin'=>	'Information Systems',
'OOR Mid Atlantic Region Director'=>	'Information Systems',
'OOR Las Vegas Office'=>	'Information Systems',
'OOR Las Vegas GSM'=>	'Information Systems',
'OOR Las Vegas DSM1'=>	'Information Systems',
'OOR Las Vegas MC1'=>	'Information Systems',
'OOR Las Vegas DSM2'=>	'Information Systems',
'OOR Las Vegas MC2'=>	'Information Systems',
'OOR Las Vegas DSM3'=>	'Information Systems',
'OOR Las Vegas MC3'=>	'Information Systems',
'OOR Las Vegas SMC1'=>	'Information Systems',
'OOR Las Vegas SMC2'=>	'Information Systems',
'OOR Las Vegas Sales Admin'=>	'Information Systems',
'OOR Phoenix Office'=>	'Information Systems',
'OOR Phoenix GSM'=>	'Information Systems',
'OOR Phoenix DSM1'=>	'Information Systems',
'OOR Phoenix MC1'=>	'Information Systems',
'OOR Phoenix DSM2'=>	'Information Systems',
'OOR Phoenix MC2'=>	'Information Systems',
'OOR Phoenix DSM3'=>	'Information Systems',
'OOR Phoenix MC3'=>	'Information Systems',
'OOR Phoenix DSM4'=>	'Information Systems',
'OOR Phoenix MC4'=>	'Information Systems',
'OOR Phoenix SMC1'=>	'Information Systems',
'OOR Phoenix SMC2'=>	'Information Systems',
'OOR Phoenix Sales Admin'=>	'Information Systems',
'OOR Harrisburg Office'=>	'Information Systems',
'OOR Harrisburg GSM'=>	'Information Systems',
'OOR Harrisburg DSM1'=>	'Information Systems',
'OOR Harrisburg MC1'=>	'Information Systems',
'OOR Harrisburg DSM2'=>	'Information Systems',
'OOR Harrisburg MC2'=>	'Information Systems',
'OOR Virginia Beach Office'=>	'Information Systems',
'OOR Virginia Beach GSM'=>	'Information Systems',
'OOR Virginia Beach DSM1'=>	'Information Systems',
'OOR Virginia Beach MC1'=>	'Information Systems',
'OOR Virginia Beach DSM2'=>	'Information Systems',
'OOR Virginia Beach MC2'=>	'Information Systems',
'OOR Virginia Beach DSM3'=>	'Information Systems',
'OOR Virginia Beach MC3'=>	'Information Systems',
'OOR Virginia Beach SMC1'=>	'Information Systems',
'OOR Oakton Office' => 'Information Systems',
'OOR Oakton GSM' => 'Information Systems',
'OOR Oakton DSM1' => 'Information Systems',
'OOR Oakton MC1' => 'Information Systems',
'OOR Oakton DSM2' => 'Information Systems',
'OOR Oakton MC2' => 'Information Systems',
'OOR Oakton DSM3' => 'Information Systems',
'OOR Oakton MC3' => 'Information Systems',
'OOR Oakton DSM4' => 'Information Systems',
'OOR Oakton MC4' => 'Information Systems',
'OOR  Oakton SMC1' => 'Information Systems',
'OOR  Oakton Sales Admin' => 'Information Systems',
'OOR SLC Senior Media Consultant1' => 'Information Systems',
'OOR SLC Senior Media Consultant3' => 'Information Systems'

    };
    
    public static Map<String, String> rolesUpdateParent = new Map<String, String>{
'OOR East and Northwest RVP'=>	'SFA Sales VP',
'OOR East Region Director'=>	'OOR East and Northwest RVP',
'OOR Allentown Office'=>	'OOR East Region Director',
'OOR Allentown GSM'=>	'OOR Allentown Office',
'OOR Allentown DSM1'=>	'OOR Allentown GSM',
'OOR Allentown MC1'=>	'OOR Allentown DSM1',
'OOR Allentown DSM2'=>	'OOR Allentown GSM',
'OOR Allentown MC2'=>	'OOR Allentown DSM2',
'OOR Allentown SMC1'=>	'OOR Allentown GSM',
'OOR Allentown Sales Admin'=>	'OOR Allentown Office',
'OOR Boston Office'=>	'OOR East Region Director',
'OOR Boston GSM'=>	'OOR Boston Office',
'OOR Boston DSM1'=>	'OOR Boston GSM',
'OOR Boston MC1'=>	'OOR Boston DSM1',
'OOR Boston DSM2'=>	'OOR Boston GSM',
'OOR Boston MC2'=>	'OOR Boston DSM2',
'OOR Boston DSM3'=>	'OOR Boston GSM',
'OOR Boston MC3'=>	'OOR Boston DSM3',
'OOR Boston SMC1'=>	'OOR Boston GSM',
'OOR Boston SMC2'=>	'OOR Boston GSM',
'OOR Boston Sales Admin'=>	'OOR Boston Office',
'OOR Long Island Office'=>	'OOR East Region Director',
'OOR Long Island GSM'=>	'OOR Long Island Office',
'OOR Long Island DSM1'=>	'OOR Long Island GSM',
'OOR Long Island MC1'=>	'OOR Long Island DSM1',
'OOR Long Island DSM2'=>	'OOR Long Island GSM',
'OOR Long Island MC2'=>	'OOR Long Island DSM2',
'OOR Long Island Sales Admin'=>'OOR Long Island Office',
'OOR New York Office'=>	'OOR East Region Director',
'OOR New York GSM1'=>	'OOR New York Office',
'OOR New York GSM2'=>	'OOR New York Office',
'OOR New York DSM1'=>	'OOR New York GSM1',
'OOR New York MC1'=>	'OOR New York DSM1',
'OOR New York DSM2'=>	'OOR New York GSM1',
'OOR New York MC2'=>	'OOR New York DSM2',
'OOR New York SMC1'=>	'OOR New York GSM2',
'OOR New York SMC2'=>	'OOR New York GSM2',
'OOR New York SMC3'=>	'OOR New York GSM2',
'OOR New York Sales Admin'=>	'OOR New York Office',
'OOR Philadelphia Office'=>	'OOR East Region Director',
'OOR Philadelphia GSM'=>	'OOR Philadelphia Office',
'OOR Philadelphia DSM1'=>	'OOR Philadelphia GSM',
'OOR Philadelphia MC1'=>	'OOR Philadelphia DSM1',
'OOR Philadelphia DSM2'=>	'OOR Philadelphia GSM',
'OOR Philadelphia MC2'=>	'OOR Philadelphia DSM2',
'OOR Philadelphia DSM3'=>	'OOR Philadelphia GSM',
'OOR Philadelphia MC3'=>	'OOR Philadelphia DSM3',
'OOR Philadelphia DSM4'=>	'OOR Philadelphia GSM',
'OOR Philadelphia MC4'=>	'OOR Philadelphia DSM4',
'OOR Philadelphia SMC1'=>	'OOR Philadelphia GSM',
'OOR Philadelphia Sales Admin'=>	'OOR Philadelphia Office',
'OOR Providence Office'=>	'OOR East Region Director',
'OOR Providence GSM'=>	'OOR Providence Office',
'OOR Providence DSM1'=>	'OOR Providence GSM',
'OOR Providence MC1'=>	'OOR Providence DSM1',
'OOR Providence DSM2'=>	'OOR Providence GSM',
'OOR Providence MC2'=>	'OOR Providence DSM2',
'OOR White Plains Office'=>	'SFA Sales Director',
'OOR White Plains MC1'=>	'OOR White Plains Office',
'OOR Northwest Region Director'=>	'OOR East and Northwest RVP',
'OOR Denver Office'=>	'OOR Northwest Region Director',
'OOR Denver GSM'=>	'OOR Denver Office',
'OOR Denver DSM1'=>	'OOR Denver GSM',
'OOR Denver MC1'=>	'OOR Denver DSM1',
'OOR Denver DSM2' =>	'OOR Denver GSM',
'OOR Denver MC2'=>	'OOR Denver DSM2',
'OOR Denver DSM3'=>	'OOR Denver GSM',
'OOR Denver MC3'=>	'OOR Denver DSM3',
'OOR Denver SMC1'=>	'OOR Denver GSM',
'OOR Denver SMC2'=>	'OOR Denver GSM',
'OOR Denver Sales Admin'=>	'OOR Denver Office',
'OOR Portland Office'=>	'OOR Northwest Region Director',
'OOR Portland GSM'=>	'OOR Portland Office',
'OOR Portland DSM1'=>	'OOR Portland GSM',
'OOR Portland MC1'=>	'OOR Portland DSM1',
'OOR Portland DSM2'=>	'OOR Portland GSM',
'OOR Portland MC2'=>	'OOR Portland DSM2',
'OOR Portland DSM3'=>	'OOR Portland GSM',
'OOR Portland MC3'=>	'OOR Portland DSM3',
'OOR Portland Sales Admin'=>	'OOR Portland Office',
'OOR Seattle Office'=>	'OOR Northwest Region Director',
'OOR Seattle GSM'=>	'OOR Seattle Office',
'OOR Seattle DSM1'=>	'OOR Seattle GSM',
'OOR Seattle MC1'=>	'OOR Seattle DSM1',
'OOR Seattle DSM2'=>	'OOR Seattle GSM',
'OOR Seattle MC2'=>	'OOR Seattle DSM2',
'OOR Seattle DSM3'=>	'OOR Seattle GSM',
'OOR Seattle MC3'=>	'OOR Seattle DSM3',
'OOR Seattle SMC1'=>	'OOR Seattle GSM',
'OOR Seattle SMC2'=>	'OOR Seattle GSM',
'OOR Seattle Sales Admin'=>	'OOR Seattle Office',
//'OOR SLC Office'=>	'OOR Northwest Region Director',
'OOR Minneapolis Office'=>	'OOR East and Northwest RVP',
'OOR Minneapolis GSM'=>	'OOR Minneapolis Office',
'OOR Minneapolis DSM1'=>	'OOR Minneapolis GSM',
'OOR Minneapolis MC1'=>	'OOR Minneapolis DSM1',
'OOR Minneapolis DSM2'=>	'OOR Minneapolis GSM',
'OOR Minneapolis MC2'=>	'OOR Minneapolis DSM2',
'OOR Minneapolis DSM3'=>	'OOR Minneapolis GSM',
'OOR Minneapolis MC3'=>	'OOR Minneapolis DSM3',
'OOR Minneapolis SMC1'=>	'OOR Minneapolis GSM',
'OOR Minneapolis SMC2'=>	'OOR Minneapolis GSM',
'OOR Minneapolis Sales Admin'=>	'OOR Minneapolis Office',
'OOR Pittsburgh Office'=>	'OOR East and Northwest RVP',
'OOR Pittsburgh GSM'=>	'OOR East and Northwest RVP',
'OOR Pittsburgh DSM1'=>	'OOR Pittsburgh GSM',
'OOR Pittsburgh MC1'=>	'OOR Pittsburgh DSM1',
'OOR Pittsburgh DSM2'=>	'OOR Pittsburgh GSM',
'OOR Pittsburgh MC2'=>	'OOR Pittsburgh DSM2',
'OOR Pittsburgh DSM3'=>	'OOR Pittsburgh GSM',
'OOR Pittsburgh MC3'=>	'OOR Pittsburgh DSM3',
'OOR Pittsburgh SMC1'=>	'OOR Pittsburgh GSM',
'OOR Pittsburgh Sales Admin'=>	'OOR Pittsburgh Office',
'OOR Mid Atlantic and Mountain West RVP'=>	'SFA Sales VP',
'OOR Mid Atlantic Region Director'=>	'OOR Mid Atlantic and Mountain West RVP',
'OOR Baltimore Office'=>	'OOR Mid Atlantic Region Director',
'OOR Baltimore GSM'=>	'OOR Baltimore Office',
'OOR Baltimore DSM1'=>	'OOR Baltimore GSM',
'OOR Baltimore MC1'=>	'OOR Baltimore DSM1',
'OOR Baltimore DSM2'=>	'OOR Baltimore GSM',
'OOR Baltimore MC2'=>	'OOR Baltimore DSM2',
'OOR Baltimore DSM3'=>	'OOR Baltimore GSM',
'OOR Baltimore MC3'=>	'OOR Baltimore DSM3',
'OOR Baltimore SMC1'=>	'OOR Baltimore GSM',
'OOR Baltimore Sales Admin'=>	'OOR Baltimore Office',
'OOR Richmond Office'=>	'OOR Mid Atlantic Region Director',
'OOR Richmond GSM'=>	'OOR Richmond Office',
'OOR Richmond DSM1'=>	'OOR Richmond GSM',
'OOR Richmond MC1'=>	'OOR Richmond DSM1',
'OOR Richmond DSM2'=>	'OOR Richmond GSM',
'OOR Richmond MC2'=>	'OOR Richmond DSM2',
'OOR Richmond SMC1'=>	'OOR Richmond GSM',
'OOR Richmond Sales Admin'=>	'OOR Richmond Office',
'OOR Las Vegas Office'=>	'OOR Mid Atlantic Region Director',
'OOR Las Vegas GSM'=>	'OOR Las Vegas Office',
'OOR Las Vegas DSM1'=>	'OOR Las Vegas GSM',
'OOR Las Vegas MC1'=>	'OOR Las Vegas DSM1',
'OOR Las Vegas DSM2'=>	'OOR Las Vegas GSM',
'OOR Las Vegas MC2'=>	'OOR Las Vegas DSM2',
'OOR Las Vegas DSM3'=>	'OOR Las Vegas GSM',
'OOR Las Vegas MC3'=>	'OOR Las Vegas DSM3',
'OOR Las Vegas SMC1'=>	'OOR Las Vegas GSM',
'OOR Las Vegas SMC2'=>	'OOR Las Vegas GSM',
'OOR Las Vegas Sales Admin'=>	'OOR Las Vegas Office',
'OOR Phoenix Office'=>	'OOR Mid Atlantic Region Director',
'OOR Phoenix GSM'=>	'OOR Phoenix Office',
'OOR Phoenix DSM1'=>	'OOR Phoenix GSM',
'OOR Phoenix MC1'=>	'OOR Phoenix DSM1',
'OOR Phoenix DSM2'=>	'OOR Phoenix GSM',
'OOR Phoenix MC2'=>	'OOR Phoenix DSM2',
'OOR Phoenix DSM3'=>	'OOR Phoenix GSM',
'OOR Phoenix MC3'=>	'OOR Phoenix DSM3',
'OOR Phoenix DSM4'=>	'OOR Phoenix GSM',
'OOR Phoenix MC4'=>	'OOR Phoenix DSM4',
'OOR Phoenix SMC1'=>	'OOR Phoenix GSM',
'OOR Phoenix SMC2'=>	'OOR Phoenix GSM',
'OOR Phoenix Sales Admin'=>	'OOR Phoenix Office',
'OOR Harrisburg Office'=>	'OOR Mid Atlantic and Mountain West RVP',
'OOR Harrisburg GSM'=>	'OOR Harrisburg Office',
'OOR Harrisburg DSM1'=>	'OOR Harrisburg GSM',
'OOR Harrisburg MC1'=>	'OOR Harrisburg DSM1',
'OOR Harrisburg DSM2'=>	'OOR Harrisburg GSM',
'OOR Harrisburg MC2'=>	'OOR Harrisburg DSM2',
'OOR Virginia Beach Office'=>	'OOR Mid Atlantic and Mountain West RVP',
'OOR Virginia Beach GSM'=>	'OOR Virginia Beach Office',
'OOR Virginia Beach DSM1'=>	'OOR Virginia Beach GSM',
'OOR Virginia Beach MC1'=>	'OOR Virginia Beach DSM1',
'OOR Virginia Beach DSM2'=>	'OOR Virginia Beach GSM',
'OOR Virginia Beach MC2'=>	'OOR Virginia Beach DSM2',
'OOR Virginia Beach DSM3'=>	'OOR Virginia Beach GSM',
'OOR Virginia Beach MC3'=>	'OOR Virginia Beach DSM3',
'OOR Virginia Beach SMC1'=>	'OOR Virginia Beach GSM',
'OOR New Jersey Office'=> 'OOR Mid Atlantic Region Director',
'OOR Salt Lake City Office'=>	'OOR Northwest Region Director',
'OOR SLC Senior Media Consultant1' => 'OOR SLC GSM',
'OOR SLC Senior Media Consultant3' => 'OOR SLC GSM',
'OOR Oakton Office' => 'OOR Mid Atlantic Region Director',
'OOR Oakton GSM' => 'OOR Oakton Office',
'OOR Oakton DSM1' => 'OOR Oakton GSM',
'OOR Oakton MC1' => 'OOR Oakton DSM1',
'OOR Oakton DSM2' => 'OOR Oakton GSM',
'OOR Oakton MC2' => 'OOR Oakton DSM2',
'OOR Oakton DSM3' => 'OOR Oakton GSM',
'OOR Oakton MC3' => 'OOR Oakton DSM3',
'OOR Oakton DSM4' => 'OOR Oakton GSM',
'OOR Oakton MC4' => 'OOR Oakton DSM4',
'OOR  Oakton SMC1' => 'OOR Oakton GSM',
'OOR  Oakton Sales Admin' => 'OOR Oakton Office'
   	
    };
    
/*
    public static Map<String, String> rolesMergeAndDelete = new Map<String, String>{
'Search CSR Manager - IR' => 'IOG EAST - Product SME - Manager',
'Search CSR - IR' => 'IOG EAST - Product SME - Rep',
'Email Support Rep' => 'IOG OOR - Support L1 - Rep',
'Email Support Manager' => 'IOG OOR - Support L1 - Manager',
'Phone Support Rep' => 'IOG OOR - Support L1 - Rep',
'Phone Support Manager' => 'IOG OOR - Support L1 - Manager',
'Credit & Collection Manager' => 'IOGCS - Undefined',
'Collection Rep' => 'IOGCS - Undefined',
'Credit Rep' => 'IOGCS - Undefined',
'Knowledge Manager' => 'IOGCS - Undefined',
'Knowledge User' => 'IOGCS - Undefined',
'Product Support Rep' =>  'IOGCS - Undefined',
'Product Support Manager' =>  'IOGCS - Undefined'	
    };

*/       
    public static String YOUREMAILBOX = [select email from User where Id =: UserInfo.getUserId()].email;
	/*public static void updateRolesFor50States() {			
		//ReLabelRoles();
		NewRoles();
		UpdateParentRoles();
		//DeleteRoles();
	}*/
/*	
	private static void ReLabelRoles(){
		String log = '';
		List<UserRole> roles = [select Id, Name from UserRole where Name IN: rolesReLabel.keySet()];
		List<UserRole> newRoles = [select Id, Name from UserRole where Name IN: rolesReLabel.values()];
		Map<String, UserRole> oldNames = new Map<String, UserRole>();
		Set<String> newNames = new Set<String>();
		for(UserRole r : roles){
			oldNames.put(r.Name, r);
		}
		for(UserRole r : newRoles){
			newNames.add(r.Name);
		}
		List<UserRole> relabels = new List<UserRole>();
		for(String s : rolesReLabel.keySet()){
			String newName = rolesRelabel.get(s);
			if(!oldNames.containsKey(s)){
				if(!newNames.contains(newName)){
					log += ' Re-label Fail : ' + s + ' not found. Re-label to the new Role ' + newName   + ' fail \n';
				}
			}else{
				if(newNames.contains(newName)){
					log += ' Re-label Warning : There will be more than one roles named ' + newName   + ' after Re-label. Please manually merge them \n';
				}
				UserRole role = oldNames.get(s);
				role.Name = rolesReLabel.get(s);
				relabels.add(role);
			}
		}
		update relabels;
		mailLogToMe('Relabel', log, YOUREMAILBOX);
	}
*/		
	/*private static void	NewRoles(){
		List<UserRole> systemRole = [select Id, Name from UserRole where Name = 'Information Systems'];
		List<UserRole> existRoles = [select Id, Name from UserRole where Name IN: rolesNew.keySet()];
		Set<String> existRoleNames = new Set<String>();
		for(UserRole r : existRoles){
			existRoleNames.add(r.Name);
		}
		
		List<UserRole> news = new List<UserRole>();
		for(String s : rolesNew.keySet()){
			if(!existRoleNames.contains(s)){
				UserRole u = new UserRole();
				u.Name = s;
				u.RollupDescription = s; 
				u.OpportunityAccessForAccountOwner = 'None';
				u.CaseAccessForAccountOwner = 'None';
				u.ParentRoleId = systemRole[0].Id;
				news.add(u);
			}
		}
		insert news;
	}
	
	private static void	UpdateParentRoles(){
		String log = '';
		List<UserRole> parentRoles = [select Id, Name from UserRole where Name IN: rolesUpdateParent.values()];
		Map<String, UserRole> pNames = new Map<String, UserRole>();
		for(UserRole r : parentRoles){
			pNames.put(r.Name, r);
		}
		List<UserRole> oldRoles = [select Id, Name from UserRole where Name IN: rolesUpdateParent.keySet()];
		Map<String, UserRole> oldextNames = new Map<String, UserRole>();
		for(UserRole r : oldRoles){
			oldextNames.put(r.Name, r);
		}		
		List<UserRole> changeParents = new List<UserRole>();
		for(String s : rolesUpdateParent.keySet()){
			if(oldextNames.containsKey(s)){
				UserRole u = oldextNames.get(s);
				UserRole p = pNames.get(rolesUpdateParent.get(s));
				if( p != null){
					u.ParentRoleId = p.Id;
					changeParents.add(u);
				}else{
					log += ' UpdateParent Fail : parent role ' + rolesUpdateParent.get(s) + ' not found. \n';
				}
			}else{
				log += ' UpdateParent Fail : old role ' + s + ' not found. \n';
			}	
		}
		update changeParents;
		mailLogToMe('UpdateParent', log, YOUREMAILBOX);
	}*/
/*	
	private static void	DeleteRoles(){
		String fromRegExp = '(.*)(@.*com)(\\..*)';
	    String toRegExp   = '$1$3$2';
        String REG_CORE   = '.*@.*com\\..*';
		Pattern refPattern_core   = Pattern.compile(REG_CORE);

		String log = '';
		List<UserRole> toRoles = [select Id, Name from UserRole where Name IN: rolesMergeAndDelete.values()];	
		Map<String, UserRole> toRoleNames = new Map<String, UserRole>();
		for(UserRole r : toRoles){
			toRoleNames.put(r.Name, r);
		}
		List<User> users = [select Id, Name, Email, UserRole.Name from User where UserRole.Name IN: rolesMergeAndDelete.keySet()];
		List<User> movedusers = new List<User>();
		Set<ID> oldRolesStillHasUsers = new Set<ID>();
		for(User u : users){
			UserRole newRole = toRoleNames.get(rolesMergeAndDelete.get(u.UserRole.Name));
			if(newRole != null){
				u.UserRoleId = newRole.Id;
				if(u.Email != null && refPattern_core.matcher(u.Email).find()){
					u.Email = u.Email.replaceAll(fromRegExp, toRegExp);
				}
				movedusers.add(u);
			}else{
				oldRolesStillHasUsers.add(u.UserRoleId);
				log += ' DeleteRoles Fail: can\'t merge users from ' + u.UserRole.Name + ', to role ' + rolesMergeAndDelete.get(u.UserRole.Name) + ' not found. \n';
			}
		}
		update movedusers;
		
		List<UserRole> mergedRoles = [select Id from UserRole where UserRole.Name IN: rolesMergeAndDelete.keySet() and Id Not IN: oldRolesStillHasUsers];
		delete mergedRoles;
		mailLogToMe('DeleteRoles', log, YOUREMAILBOX);
	}
*/    		 

/**** Created by PLo ****/

   private static String updateLog = '';
	/* 
	   AD-23850, Adworks role update
	   
	   this is part one of the whole process, updating data
	   i. update role names
	   ii. add new roles under SVP - AdWorks
	   iii. update role parents
	   iv. reassign users under deleting roles
	   v. delete roles
	*/
   public static void updateAASRoleNames()
   {
   	// merge users, both are old names      
      Map<String,String> consolidateUsersUnderRole = new Map<String,String>
      {
      	'Yellow Pages Sales' => 'Senior Manager Sales Operations'
      };
   	
      Map<String,String> roleReplaceMatrix = new Map<String,String>
      {
      	'SVP of Sales - Advanced Ad Solutions' => 'SVP - AdWorks',
      	'AAS Billings' => 'AdWorks Billings',
      	'AAS Collections' => 'AdWorks Collections',
			'AAS Operations' => 'AdWorks Operations',
			'AAS VISITOR' => 'AdWorks VISITOR',
			'BNI-CMR' => 'BNI-CMR',
			'Director Client Services' => 'Director Client Servies Online/Mobile',
			'Account Manager' => 'Senior Account Manager Online/Mobile',
			//'Yellow Pages Sales' => 'Senior Manager Ad Trafficking Online/Mobile',
			'Regional VP Product Development' => 'RVP Product Development',
			'Product Development Manager' => 'Director Product Development',
			'Product Development AE' => 'Senior Manager Product Development',
			'IPTV-Prod Mkt AE' => 'Senior Manager IPTV Product Marketing',
			'Director Mobile (Central)' => 'Director Online/Mobile (Central)',
			'Director Mobile (East)' => 'Director Online/Mobile (East)',
			'Mobile (East) AE' => 'Mobile (East) AE',
			'Director Mobile (West)' => 'Director Online/Mobile (West)',
			'Mobile (West) AE' => 'Mobile (West) AE',
			'Online (Central) AE' => 'Online (Central) AE',
			'Online (East) AE' => 'Online (East) AE',
			'Online (West) AE' => 'Online (West) AE',
			'RVP Sales Development (S&D)' => 'RVP Business Development',
			'Director Development (S&D)' => 'Director Business Development',
			'Development (S&D) AE' => 'Senior Manager Business Development',
			'VP AAS Marketing' => 'RVP Marketing',
			'Director AAS Marketing' => 'Director AdWorks Marketing',
			'AAS Marketing AE' => 'AdWorks Marketing Manager',
			'Director AAS Media Innovation' => 'Director AdWorks Media Innovation',
			'AAS Media Innovation AE' => 'AdWorks Media Innovation Manager',
			'Director AAS Media Lab' => 'Director AdWorks Media Lab',
			'AAS Media Lab AE' => 'AdWorks Media Lab Manager',
			'VP Product Marketing & Ops' => 'VP Product & Operations',
			'VP Mobile Product' => 'RVP Product Marketing',
			'Director Consumables Product' => 'Senior Manager Mobile Consumables',
			'Director Mobile Product' => 'Director Mobile Product Marketing',
			'Mobile Product AE' => 'Senior Manager Mobile Product Marketing',
			'Director Online/Data Product' => 'Director Online/Data Product Marketing',
			'Online/Data Product AE' => 'Senior Manager Online/Data Marketing',
			'VP Sales Operations' => 'RVP Business Operations',
			'Director National Price & Plan' => 'Director Ad Operations Online/Mobile',
			'Manager National Price & Plan' => 'Senior Manager Pricing & Inventory Online/Mobile',
			'AE National Price & Plan' => 'Manager Pricing & Inventory Online/Mobile',
			'Senior Manager Sales Operations' => 'Senior Manager Ad Trafficking Online/Mobile'
      };
      
      // make role name as keys
      Map<String,UserRole> updateMap = new Map<String,UserRole>();
      List<UserRole> urList = [SELECT Name, RollupDescription, (SELECT Email, UserRoleId FROM Users) FROM UserRole 
                               WHERE Name IN :roleReplaceMatrix.keyset() OR Name IN :consolidateUsersUnderRole.keyset()];
      for(UserRole ur : urList)
      {
      	updateMap.put(ur.Name, ur);
      }
      
      List<User> updateUser = new List<User>();
      for(String oldName : consolidateUsersUnderRole.keyset())
      {
      	if(updateMap.containskey(oldName))
      	{
      		for(User u : updateMap.get(oldName).Users)
      		{
      			u.UserRoleId = updateMap.get(consolidateUsersUnderRole.get(oldName)).Id;
      			
      			if(u.Email != null && u.Email.substring(u.Email.length()-4) != '.com')
      			   u.Email = 'null@att-temp.com';
      			
      			updateUser.add(u);
      		}
      	}
      }
      
      update updateUser;
      
      List<UserRole> toAddRolesToSync = new List<UserRole>();
      
      for(String oldName : roleReplaceMatrix.keyset())
      {
      	if(updateMap.containskey(oldName))
      	{
      	   UserRole ur = updateMap.get(oldName);
      	   ur.Name = roleReplaceMatrix.get(oldName);
      	   //ur.RollupDescription = ur.Name;
      	         	
      	   updateLog += '- updating ' + ur.Id + ': ' + oldName + ' => ' + ur.Name + '\r\n';
      	}
      	else
      	{
      		UserRole ur = new UserRole();
      		ur.Name = roleReplaceMatrix.get(oldName);
      		ur.ParentRoleId = updateMap.get('SVP of Sales - Advanced Ad Solutions').Id;
      		toAddRolesToSync.add(ur);
      		
      	   updateLog += '- entry not found: ' + oldName + '\r\n';     
      	} 	
      }
      
      insert toAddRolesToSync;
      
      updateLog += buildSaveResultLog(Database.update(updateMap.values(),false));
   }
   
   public static void addNewAASRoles()
   {
   	String tempParentURName = 'SVP - AdWorks';
   	
   	// report to 'SVP - AdWorks' first
   	Map<String,String> newRolesWithParent = new Map<String,String>
   	{
   		'Manager Online/Mobile' => tempParentURName,
   		'Director Mobile Project Management' => tempParentURName,
   		'Senior Manager Sales Planning Online/Mobile' => tempParentURName,
   		'Manager Sales Planning Online/Mobile' => tempParentURName,
   		'RVP Audience Development' => tempParentURName,
			'Director U-verse Sales and Operations' => tempParentURName,
			'Senior Manager U-verse Ad Operations' => tempParentURName,
			'Manager U-verse Ad Operations' => tempParentURName,
			'Senior Manager U-verse Sales Planning' => tempParentURName,
			'Manager U-verse Sales Planning' => tempParentURName
   	};
   	
   	List<UserRole> urToAdd = new List<UserRole>();
   	Map<String,UserRole> aasNewRolesMap = new Map<String,UserRole>();
   	List<UserRole> aasNewRoles = [SELECT Name FROM UserRole 
   	                              WHERE Name IN :newRolesWithParent.keyset() OR Name = :tempParentURName];
   	                              
   	for(UserRole ur : aasNewRoles)
   	{
   		aasNewRolesMap.put(ur.Name,ur);
   	}                              
   	
   	for(String nURName : newRolesWithParent.keyset())
   	{
   		if(!aasNewRolesMap.keyset().contains(nURName))
   		{
	   		UserRole nr = new UserRole();
	   		nr.Name = nURName;
	   		nr.RollupDescription = nr.Name;
	   		nr.ParentRoleId = aasNewRolesMap.get(tempParentURName).Id;
	   		urToAdd.add(nr);
	   		
	   		updateLog += '- inserting: ' + nURName + ' with Parent Role: ' + newRolesWithParent.get(nURName) + '\r\n';
   		}   		
   		else
   		{
   			updateLog += '- inserting: ' + nURName + ' already existed, skipping creation\r\n';
   		}
   	}   	
   	
   	updateLog += buildSaveResultLog(Database.insert(urToAdd,false));
   }
   
   public static void updateAASParentRoles()
   {
   	Map<String,String> updatedRoleParentMatrix = new Map<String,String>
      {
      	'Manager Online/Mobile' => 'Senior Account Manager Online/Mobile',
			'Director Mobile Project Management' => 'RVP Product Marketing',
			'Senior Manager Sales Planning Online/Mobile' => 'Director Client Servies Online/Mobile',
			'Manager Sales Planning Online/Mobile' => 'Senior Manager Sales Planning Online/Mobile',
			'RVP Audience Development' => 'VP Product & Operations',
			'AdWorks Billings' => 'RVP Business Operations',
			'AdWorks Collections' => 'RVP Business Operations',
			'AdWorks Operations' => 'RVP Business Operations',
			'AdWorks VISITOR' => 'RVP Business Operations',
			'BNI-CMR' => 'RVP Business Operations',
			'Director Client Servies Online/Mobile' => 'RVP Business Operations',
			'Senior Account Manager Online/Mobile' => 'Director Client Servies Online/Mobile',
			'Senior Manager Ad Trafficking Online/Mobile' => 'Director Ad Operations Online/Mobile',
			'RVP Product Development' => 'VP Product & Operations',
			'Director Product Development' => 'RVP Product Development',
			'Senior Manager Product Development' => 'Director Product Development',
			'Senior Manager IPTV Product Marketing' => 'Director IPTV-Prod Mkt',
			'Director Online/Mobile (Central)' => 'RVP Online/Mobile Sales',
			'Director Online/Mobile (East)' => 'RVP Online/Mobile Sales',
			'Mobile (East) AE' => 'Director Online/Mobile (East)',
			'Director Online/Mobile (West)' => 'RVP Online/Mobile Sales',
			'Mobile (West) AE' => 'Director Online/Mobile (West)',
			'Online (Central) AE' => 'Director Online/Mobile (Central)',
			'Online (East) AE' => 'Director Online/Mobile (East)',
			'Online (West) AE' => 'Director Online/Mobile (West)',
			'RVP Business Development' => 'SVP - AdWorks',
			'Director Business Development' => 'RVP Online/Mobile Sales',
			'Senior Manager Business Development' => 'Director Business Development',
			'RVP Marketing' => 'SVP - AdWorks',
			'Director AdWorks Marketing' => 'RVP Marketing',
			'AdWorks Marketing Manager' => 'Director AdWorks Marketing',
			'Director AdWorks Media Innovation' => 'RVP Marketing',
			'AdWorks Media Innovation Manager' => 'Director AdWorks Media Innovation',
			'Director AdWorks Media Lab' => 'RVP Marketing',
			'AdWorks Media Lab Manager' => 'Director AdWorks Media Lab',
			'VP Product & Operations' => 'SVP - AdWorks',
			'RVP Product Marketing' => 'VP Product & Operations',
			'Senior Manager Mobile Consumables' => 'Director Client Servies Online/Mobile',
			'Director Mobile Product Marketing' => 'RVP Product Marketing',
			'Senior Manager Mobile Product Marketing' => 'Director Mobile Product Marketing',
			'Director Online/Data Product Marketing' => 'RVP Product Marketing',
			'Senior Manager Online/Data Marketing' => 'Director Online/Data Product Marketing',
			'RVP Business Operations' => 'VP Product & Operations',
			'Director Ad Operations Online/Mobile' => 'RVP Business Operations',
			'Senior Manager Pricing & Inventory Online/Mobile' => 'Director Ad Operations Online/Mobile',
			'Manager Pricing & Inventory Online/Mobile' => 'Senior Manager Pricing & Inventory Online/Mobile',
			'RVP Central/West Integrated Sales' => 'SVP - AdWorks',
			'RVP East Integrated Sales' => 'SVP - AdWorks',
			'RVP IPTV Media Sales' => 'SVP - AdWorks',
			'Director IPTV-Prod Mkt' => 'RVP Product Marketing',
			'Mobile (Central) AE' => 'Director Online/Mobile (Central)',
			'Director Search/Core' => 'VP Product & Operations',
			'Director U-verse Sales and Operations' => 'RVP Business Operations',
			'Senior Manager U-verse Ad Operations' => 'Director U-verse Sales and Operations',
			'Manager U-verse Ad Operations' => 'Senior Manager U-verse Ad Operations',
			'Senior Manager U-verse Sales Planning' => 'Director U-verse Sales and Operations',
			'Manager U-verse Sales Planning' => 'Senior Manager U-verse Sales Planning'
			
			//'Senior Manager Ad Trafficking Online/Mobile' => 'Director Ad Operations Online/Mobile'
      };
      
      List<UserRole> urList = [SELECT Name, ParentRoleId FROM UserRole 
                               WHERE Name IN :updatedRoleParentMatrix.keyset() OR 
                                     Name IN ('RVP Online/Mobile Sales','SVP - AdWorks','Director IPTV-Prod Mkt')];
      Map<String,UserRole> urListMap = new Map<String,UserRole>();
      for(UserRole ur : urList)
      {
      	urListMap.put(ur.Name,ur);
      }
      
      for(String urName : updatedRoleParentMatrix.keyset())
      {
      	if(urListMap.containsKey(urName))
      	{
	      	UserRole ur = urListMap.get(urName);
	      	UserRole urParent = urListMap.get(updatedRoleParentMatrix.get(urName));
	      	
	      	if(urParent != null)
	      	{
	      	   ur.ParentRoleId = urParent.Id;
	      	
	      	   updateLog += '- updating parent role: ' + urName + ' => ' + urParent.Name + '\r\n';
	      	}
	      	else
	      	{
	      		updateLog += '- updating parent role: ' + urName + ' => assigning parent is not found\r\n';
	      	}
      	}
      	else
      	{
      		updateLog += '- updating parent role: ' + urName + ' => is not found\r\n';
      	}
      }
      
      updateLog += buildSaveResultLog(Database.update(urListMap.values(),false));
   }
   
   // Reassign users to another role, role is TBD, so make them blank right now
   public static void ReassignUsersAndDeleteRoles()
   {
   	Map<String,String> userRoleMap = new Map<String,String>
   	{
   		'Tony Tramontana' => null,
   		'Mike Fordyce' => null,
			'Todd Rose' => null,
			'Will Lowry' => null,
			'Brendon Gallagher' => null
   	};
   	
   	Map<String,UserRole> assignedRoleMap = new Map<String,UserRole>();
   	List<UserRole> assignedRoles = [SELECT Name FROM UserRole WHERE Name IN :userRoleMap.values()];
   	for(UserRole ur : assignedRoles)
   	{
   		assignedRoleMap.put(ur.Name,ur);
   	}
   	
   	List<User> userList = [SELECT Name, UserRoleId FROM User WHERE Name IN :userRoleMap.keyset()];
   	for(User u : userList)
   	{
   		Id movedTo = null;
   		
   		if(userRoleMap.get(u.Name) != null)
   		{
   			movedTo = assignedRoleMap.get(userRoleMap.get(u.Name)).Id;
   		}
   		
   		u.UserRoleId = movedTo;
   		
   		updateLog += '- updating user role: ' + u.Name + ' is updated to role ' + userRoleMap.get(u.Name) + '\r\n';
   	}
   	
   	updateLog += buildSaveResultLog(Database.update(userList,false));
   	
   	// deleting roles
   	List<String> roleNamesToDelete = new List<String>
   	{
			'ADSAM',
			'Manager of Ad Operations',
			'Pre-Sales Director',
			'Pre-Sales Manager',
			'Regional VP Central',
			'Central Sales Manager',
			'Central AE',
			'Regional VP East',
			'East Coast Sales Manager',
			'East AE',
			'East Coast Account Manager',
			'RSAM East',
			'Regional VP West',
			'RSAM West',
			'West Coast Sales Manager',
			'West AE',
			'West Coast Account Manager',
			'Director Online (Central)',
			'Director Online (East)',
			'Director Online (West)',
			'Director Distribution (S&D)',
			'Distribution (S&D) AE',
			'VP Mobility',
			'Mobility Manager',
			'Consumables Product AE',
			'VP Online/Data',
			'Product Research AE',
			'VP of BusDev/PartnerManagement',
			'BD Distribution Director',
			'BD Distribution Manager',
			'BD Executive Director',
			'BD Mobile Director',
			'BD Third Parties',
			'BD Strategy Director',
			'BD Strategy Manager',
			'Partnership Management Director',
			'Partner Manager',
			'Director Product Research',
			'Yellow Pages Sales'
   	};
   	
   	List<UserRole> roleToDelete = [SELECT Name, ParentRoleId, (SELECT Id, Email FROM Users) FROM UserRole WHERE NAME IN :roleNamesToDelete];
   	List<User> userToRemoveRole = new List<User>();
   	
   	for(UserRole ur : roleToDelete)
   	{
   		// if there are users that weren't caught
   		for(User u : ur.Users)
   		{
   			u.UserRoleId = null;
   			userToRemoveRole.add(u);
   			if(u.Email != null && u.Email.substring(u.Email.length()-4) != '.com')
   			   u.Email = 'null@att-temp.com';
   		}
   		
   		ur.ParentRoleId = null;
   	}
   	
   	update roleToDelete;
   	update userToRemoveRole;
   	delete roleToDelete;
   }
   
   private static String buildSaveResultLog(List<Database.SaveResult> results)
   {
   	String srLog = '';
   	for(Database.SaveResult sr : results)
   	{
   	   srLog += '\r\nupdate status for Id ' + sr.getId() + ': ' + (sr.isSuccess() ? 'COMPLETED' : 'FAILED');
   	   if(!sr.isSuccess())
   	   {
   	   	Integer i = 1;
	      	for(Database.Error er : sr.getErrors())
	      	{
	      		srLog += '\r\nerror message ' + i + ': ' + er.getMessage();
	      		i++;
	      	}
   	   }
   	   
   	}
   	srLog += '\r\n';
   	return srLog;
   }
   
   public static void UpdateAASRole()
   {
   	try
   	{
	   	updateLog = 'Process result for: Updating AAS Names\r\n\r\n';
	   	updateAASRoleNames();
	   	
	   	updateLog += 'Process result for: Inserting AAS Roles\r\n\r\n';
	   	addNewAASRoles();
	   	
	   	updateLog += 'Process result for: Update AAS Role Parents\r\n\r\n';
	   	updateAASParentRoles();
	   	
	   	updateLog += 'Process result for: Update User Role \r\n\r\n';
	   	ReassignUsersAndDeleteRoles();
   	}
   	catch(Exception ex)
   	{
   		updateLog += 'Update failed:\r\n\r\nCause:' + ex.getCause();
   		updateLog += '\r\nLineNumbetr:' + ex.getLineNumber();
   		updateLog += '\r\n\r\nStack:' + ex.getStackTraceString();
   		updateLog += '\r\n\r\nMessage:' + ex.getMessage();
   		updateLog += '\r\n\r\nType:' + ex.getTypeName();
   	}
   	finally
   	{
   	    mailLogToMe('Updating AAS Names', updateLog, 'plo@attinteractive.com');	
   	}
   }
   
/**** End ****/

/*****************************************************************************************
   Main running methods
*****************************************************************************************/
	private static void mailLogToMe(String subject, String log, String email){
		if(log != ''){
			Messaging.SingleEmailMessage mail =new Messaging.SingleEmailMessage();
		    String[] toAddresses = new String[] {email};
		    mail.setToAddresses(toAddresses);
		    mail.setReplyTo(email);
		    mail.setSenderDisplayName('Debug log ');
		    mail.setSubject('Data migration :' + subject + ' User Name : ' + UserInfo.getUserName());
		    mail.setPlainTextBody(log);
		    Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });	
		}	
	}

	global Database.Querylocator start(Database.BatchableContext bc){
		String query = 'select id from user limit 1';
        return Database.getQueryLocator(query);		
	}
	
	global void execute(Database.BatchableContext bc, List<sObject> scope){
	}
	
	global void finish(Database.BatchableContext bc){
		//updateRolesFor50States();
	}	
	
	// Test
	public static testMethod void testrun() {
		//updateRolesFor50States();
		User currentUser = [SELECT Name FROM User WHERE Id = :UserInfo.getUserId()];
		
		system.runAs(currentUser) // ignores user license limit
		{
			UpdateAASRole();
		}
		
		database.executebatch(new tests());
		
		signupUsers();
	}
/******************************************************************************************
   End
*****************************************************************************************/

	public static void signupUsers(){
		Map<String, String> userlist = new Map<String, String>{
												//'jn6146' => 'Jasmine;Nelson;IOG Support - Standard - East;IOG EAST - Support L1 - Rep',
												//'th6944' => 'Teresa;Horn;IOG Support - Standard - East;IOG EAST - Support L1 - Supervisor',
												//'mt028Q' => 'Miranda;Thomas;IOG Support - Standard - East;IOG EAST - Support L1 - Rep'
												};
											   
		Set<String> profnames = new Set<String>{'IOG Support - Standard - East'};

		Set<String> rolenames = new Set<String>{'IOG EAST - Support L1 - Manager'
											   ,'IOG EAST - Support L1 - Rep'
											   ,'IOG EAST - Support L1 - Supervisor'};
		List<Profile> ps  = [select id, name from Profile  where Name IN: profnames];
		List<UserRole> rs = [select id, name from UserRole where Name IN: rolenames];
		Map<String, ID> profiles = new Map<String, ID>();
		Map<String, ID> roles = new Map<String, ID>();
		for(Profile p : ps){
			profiles.put(p.name, p.Id);
		}
		for(UserRole r : rs){
			roles.put(r.name, r.Id);
		}
		
		List<User> newusers = new List<User>();
		for(String s : userlist.keySet()){
			User u = new User(isActive=true,LanguageLocaleKey='en_US',TimeZoneSidKey='America/New_York', LocaleSidKey='en_US',EmailEncodingKey='UTF-8');
			u.ATTUID__c = s;
			u.Email = s + '.test@att.com';
			u.Username = s + '@att.com.test';
			u.CommunityNickname = s;
			u.Alias = s;
			String[] ss = userlist.get(s).split(';');			
			u.FirstName = ss[0];
			u.LastName = ss[1];
			u.ProfileId = profiles.get(ss[2]);
			u.UserRoleId = roles.get(ss[3]);
			newusers.add(u);
		}
		insert newusers;
		for(User u : newusers){
			System.debug(u.FirstName + '' + u.LastName + ' is done');
			System.setPassword(u.Id, '123123a');
		}
		
	}
	
	
}